/*
 * ! Ext JS Library 3.3.1 Copyright(c) 2006-2010 Sencha Inc.
 * licensing@sencha.com http://www.sencha.com/license
 */
// for old browsers
window.undefined = window.undefined;

/**
 * @class Ext Ext core utilities and functions.
 * @singleton
 */

Ext = {
	/**
	 * The version of the framework
	 * 
	 * @type String
	 */
	version : '3.3.1',
	versionDetail : {
		major : 3,
		minor : 3,
		patch : 1
	}
};

/**
 * Copies all the properties of config to obj.
 * 
 * @param {Object}
 *            obj The receiver of the properties
 * @param {Object}
 *            config The source of the properties
 * @param {Object}
 *            defaults A different object that will also be applied for default
 *            values
 * @return {Object} returns obj
 * @member Ext apply
 */
Ext.apply = function(o, c, defaults) {
	// no "this" reference for friendly out of scope calls
	if (defaults) {
		Ext.apply(o, defaults);
	}
	if (o && c && typeof c == 'object') {
		for (var p in c) {
			o[p] = c[p];
		}
	}
	return o;
};

(function() {
	var idSeed = 0, toString = Object.prototype.toString, ua = navigator.userAgent
			.toLowerCase(), check = function(r) {
		return r.test(ua);
	}, DOC = document, docMode = DOC.documentMode, isStrict = DOC.compatMode == "CSS1Compat", isOpera = check(/opera/), isChrome = check(/\bchrome\b/), isWebKit = check(/webkit/), isSafari = !isChrome
			&& check(/safari/), isSafari2 = isSafari && check(/applewebkit\/4/), // unique
																					// to
																					// Safari
																					// 2
	isSafari3 = isSafari && check(/version\/3/), isSafari4 = isSafari
			&& check(/version\/4/), isIE = !isOpera && check(/msie/), isIE7 = isIE
			&& (check(/msie 7/) || docMode == 7), isIE8 = isIE
			&& (check(/msie 8/) && docMode != 7), isIE6 = isIE && !isIE7
			&& !isIE8, isGecko = !isWebKit && check(/gecko/), isGecko2 = isGecko
			&& check(/rv:1\.8/), isGecko3 = isGecko && check(/rv:1\.9/), isBorderBox = isIE
			&& !isStrict, isWindows = check(/windows|win32/), isMac = check(/macintosh|mac os x/), isAir = check(/adobeair/), isLinux = check(/linux/), isSecure = /^https/i
			.test(window.location.protocol);

	// remove css image flicker
	if (isIE6) {
		try {
			DOC.execCommand("BackgroundImageCache", false, true);
		} catch (e) {
		}
	}

	Ext.apply(Ext, {
		/**
		 * URL to a blank file used by Ext when in secure mode for iframe src
		 * and onReady src to prevent the IE insecure content warning (<tt>'about:blank'</tt>,
		 * except for IE in secure mode, which is <tt>'javascript:""'</tt>).
		 * 
		 * @type String
		 */
		SSL_SECURE_URL : isSecure && isIE ? 'javascript:""' : 'about:blank',
		/**
		 * True if the browser is in strict (standards-compliant) mode, as
		 * opposed to quirks mode
		 * 
		 * @type Boolean
		 */
		isStrict : isStrict,
		/**
		 * True if the page is running over SSL
		 * 
		 * @type Boolean
		 */
		isSecure : isSecure,
		/**
		 * True when the document is fully initialized and ready for action
		 * 
		 * @type Boolean
		 */
		isReady : false,

		/**
		 * True if the {@link Ext.Fx} Class is available
		 * 
		 * @type Boolean
		 * @property enableFx
		 */

		/**
		 * HIGHLY EXPERIMENTAL True to force css based border-box model override
		 * and turning off javascript based adjustments. This is a runtime
		 * configuration and must be set before onReady.
		 * 
		 * @type Boolean
		 */
		enableForcedBoxModel : false,

		/**
		 * True to automatically uncache orphaned Ext.Elements periodically
		 * (defaults to true)
		 * 
		 * @type Boolean
		 */
		enableGarbageCollector : true,

		/**
		 * True to automatically purge event listeners during garbageCollection
		 * (defaults to false).
		 * 
		 * @type Boolean
		 */
		enableListenerCollection : false,

		/**
		 * EXPERIMENTAL - True to cascade listener removal to child elements
		 * when an element is removed. Currently not optimized for performance.
		 * 
		 * @type Boolean
		 */
		enableNestedListenerRemoval : false,

		/**
		 * Indicates whether to use native browser parsing for JSON methods.
		 * This option is ignored if the browser does not support native JSON
		 * methods. <b>Note: Native JSON methods will not work with objects that
		 * have functions. Also, property names must be quoted, otherwise the
		 * data will not parse.</b> (Defaults to false)
		 * 
		 * @type Boolean
		 */
		USE_NATIVE_JSON : false,

		/**
		 * Copies all the properties of config to obj if they don't already
		 * exist.
		 * 
		 * @param {Object}
		 *            obj The receiver of the properties
		 * @param {Object}
		 *            config The source of the properties
		 * @return {Object} returns obj
		 */
		applyIf : function(o, c) {
			if (o) {
				for (var p in c) {
					if (!Ext.isDefined(o[p])) {
						o[p] = c[p];
					}
				}
			}
			return o;
		},

		/**
		 * Generates unique ids. If the element already has an id, it is
		 * unchanged
		 * 
		 * @param {Mixed}
		 *            el (optional) The element to generate an id for
		 * @param {String}
		 *            prefix (optional) Id prefix (defaults "ext-gen")
		 * @return {String} The generated Id.
		 */
		id : function(el, prefix) {
			el = Ext.getDom(el, true) || {};
			if (!el.id) {
				el.id = (prefix || "ext-gen") + (++idSeed);
			}
			return el.id;
		},

		/**
		 * <p>
		 * Extends one class to create a subclass and optionally overrides
		 * members with the passed literal. This method also adds the function
		 * "override()" to the subclass that can be used to override members of
		 * the class.
		 * </p>
		 * For example, to create a subclass of Ext GridPanel:
		 * 
		 * <pre><code>
		 * 		MyGridPanel = Ext.extend(Ext.grid.GridPanel, {
		 * 		constructor: function(config) {
		 * 
		 * 		//      Create configuration for this Grid.
		 * 		var store = new Ext.data.Store({...});
		 * 		var colModel = new Ext.grid.ColumnModel({...});
		 * 
		 * 		//      Create a new config object containing our computed properties
		 * 		//      *plus* whatever was in the config parameter.
		 * 		config = Ext.apply({
		 * 		    store: store,
		 * 		    colModel: colModel
		 * 		}, config);
		 * 
		 * 		MyGridPanel.superclass.constructor.call(this, config);
		 * 
		 * 		//      Your postprocessing here
		 * 		},
		 * 
		 * 		yourMethod: function() {
		 * 		// etc.
		 * 		}
		 * 		});
		 * 		
		 * </code></pre>
		 * 
		 * <p>
		 * This function also supports a 3-argument call in which the subclass's
		 * constructor is passed as an argument. In this form, the parameters
		 * are as follows:
		 * </p>
		 * <div class="mdetail-params">
		 * <ul>
		 * <li><code>subclass</code> : Function <div class="sub-desc">The
		 * subclass constructor.</div></li>
		 * <li><code>superclass</code> : Function <div class="sub-desc">The
		 * constructor of class being extended</div></li>
		 * <li><code>overrides</code> : Object <div class="sub-desc">A
		 * literal with members which are copied into the subclass's prototype,
		 * and are therefore shared among all instances of the new class.</div></li>
		 * </ul>
		 * </div>
		 * 
		 * @param {Function}
		 *            superclass The constructor of class being extended.
		 * @param {Object}
		 *            overrides
		 *            <p>
		 *            A literal with members which are copied into the
		 *            subclass's prototype, and are therefore shared between all
		 *            instances of the new class.
		 *            </p>
		 *            <p>
		 *            This may contain a special member named
		 *            <tt><b>constructor</b></tt>. This is used to define
		 *            the constructor of the new class, and is returned. If this
		 *            property is <i>not</i> specified, a constructor is
		 *            generated and returned which just calls the superclass's
		 *            constructor passing on its parameters.
		 *            </p>
		 *            <p>
		 *            <b>It is essential that you call the superclass
		 *            constructor in any provided constructor. See example code.</b>
		 *            </p>
		 * @return {Function} The subclass constructor from the
		 *         <code>overrides</code> parameter, or a generated one if not
		 *         provided.
		 */
		extend : function() {
			// inline overrides
			var io = function(o) {
				for (var m in o) {
					this[m] = o[m];
				}
			};
			var oc = Object.prototype.constructor;

			return function(sb, sp, overrides) {
				if (typeof sp == 'object') {
					overrides = sp;
					sp = sb;
					sb = overrides.constructor != oc
							? overrides.constructor
							: function() {
								sp.apply(this, arguments);
							};
				}
				var F = function() {
				}, sbp, spp = sp.prototype;

				F.prototype = spp;
				sbp = sb.prototype = new F();
				sbp.constructor = sb;
				sb.superclass = spp;
				if (spp.constructor == oc) {
					spp.constructor = sp;
				}
				sb.override = function(o) {
					Ext.override(sb, o);
				};
				sbp.superclass = sbp.supr = (function() {
					return spp;
				});
				sbp.override = io;
				Ext.override(sb, overrides);
				sb.extend = function(o) {
					return Ext.extend(sb, o);
				};
				return sb;
			};
		}(),

		/**
		 * Adds a list of functions to the prototype of an existing class,
		 * overwriting any existing methods with the same name. Usage:
		 * 
		 * <pre><code>
		 * Ext.override(MyClass, {
		 * 			newMethod1 : function() {
		 * 				// etc.
		 * 			},
		 * 			newMethod2 : function(foo) {
		 * 				// etc.
		 * 			}
		 * 		});
		 * </code></pre>
		 * 
		 * @param {Object}
		 *            origclass The class to override
		 * @param {Object}
		 *            overrides The list of functions to add to origClass. This
		 *            should be specified as an object literal containing one or
		 *            more methods.
		 * @method override
		 */
		override : function(origclass, overrides) {
			if (overrides) {
				var p = origclass.prototype;
				Ext.apply(p, overrides);
				if (Ext.isIE && overrides.hasOwnProperty('toString')) {
					p.toString = overrides.toString;
				}
			}
		},

		/**
		 * Creates namespaces to be used for scoping variables and classes so
		 * that they are not global. Specifying the last node of a namespace
		 * implicitly creates all other nodes. Usage:
		 * 
		 * <pre><code>
		 * 		Ext.namespace('Company', 'Company.data');
		 * 		Ext.namespace('Company.data'); // equivalent and preferable to above syntax
		 * 		Company.Widget = function() { ... }
		 * 		Company.data.CustomStore = function(config) { ... }
		 * 		
		 * </code></pre>
		 * 
		 * @param {String}
		 *            namespace1
		 * @param {String}
		 *            namespace2
		 * @param {String}
		 *            etc
		 * @return {Object} The namespace object. (If multiple arguments are
		 *         passed, this will be the last namespace created)
		 * @method namespace
		 */
		namespace : function() {
			var o, d;
			Ext.each(arguments, function(v) {
						d = v.split(".");
						o = window[d[0]] = window[d[0]] || {};
						Ext.each(d.slice(1), function(v2) {
									o = o[v2] = o[v2] || {};
								});
					});
			return o;
		},

		/**
		 * Takes an object and converts it to an encoded URL. e.g.
		 * Ext.urlEncode({foo: 1, bar: 2}); would return "foo=1&bar=2".
		 * Optionally, property values can be arrays, instead of keys and the
		 * resulting string that's returned will contain a name/value pair for
		 * each array value.
		 * 
		 * @param {Object}
		 *            o
		 * @param {String}
		 *            pre (optional) A prefix to add to the url encoded string
		 * @return {String}
		 */
		urlEncode : function(o, pre) {
			var empty, buf = [], e = encodeURIComponent;

			Ext.iterate(o, function(key, item) {
				empty = Ext.isEmpty(item);
				Ext.each(empty ? key : item, function(val) {
							buf
									.push(
											'&',
											e(key),
											'=',
											(!Ext.isEmpty(val) && (val != key || !empty))
													? (Ext.isDate(val)
															? Ext
																	.encode(val)
																	.replace(
																			/"/g,
																			'')
															: e(val))
													: '');
						});
			});
			if (!pre) {
				buf.shift();
				pre = '';
			}
			return pre + buf.join('');
		},

		/**
		 * Takes an encoded URL and and converts it to an object. Example:
		 * 
		 * <pre><code>
		 * Ext.urlDecode(&quot;foo=1&amp;bar=2&quot;); // returns {foo: &quot;1&quot;, bar: &quot;2&quot;}
		 * Ext.urlDecode(&quot;foo=1&amp;bar=2&amp;bar=3&amp;bar=4&quot;, false); // returns {foo: &quot;1&quot;, bar: [&quot;2&quot;, &quot;3&quot;, &quot;4&quot;]}
		 * </code></pre>
		 * 
		 * @param {String}
		 *            string
		 * @param {Boolean}
		 *            overwrite (optional) Items of the same name will overwrite
		 *            previous values instead of creating an an array (Defaults
		 *            to false).
		 * @return {Object} A literal with members
		 */
		urlDecode : function(string, overwrite) {
			if (Ext.isEmpty(string)) {
				return {};
			}
			var obj = {}, pairs = string.split('&'), d = decodeURIComponent, name, value;
			Ext.each(pairs, function(pair) {
						pair = pair.split('=');
						name = d(pair[0]);
						value = d(pair[1]);
						obj[name] = overwrite || !obj[name] ? value : []
								.concat(obj[name]).concat(value);
					});
			return obj;
		},

		/**
		 * Appends content to the query string of a URL, handling logic for
		 * whether to place a question mark or ampersand.
		 * 
		 * @param {String}
		 *            url The URL to append to.
		 * @param {String}
		 *            s The content to append to the URL.
		 * @return (String) The resulting URL
		 */
		urlAppend : function(url, s) {
			if (!Ext.isEmpty(s)) {
				return url + (url.indexOf('?') === -1 ? '?' : '&') + s;
			}
			return url;
		},

		/**
		 * Converts any iterable (numeric indices and a length property) into a
		 * true array Don't use this on strings. IE doesn't support "abc"[0]
		 * which this implementation depends on. For strings, use this instead:
		 * "abc".match(/./g) => [a,b,c];
		 * 
		 * @param {Iterable}
		 *            the iterable object to be turned into a true Array.
		 * @return (Array) array
		 */
		toArray : function() {
			return isIE ? function(a, i, j, res) {
				res = [];
				for (var x = 0, len = a.length; x < len; x++) {
					res.push(a[x]);
				}
				return res.slice(i || 0, j || res.length);
			} : function(a, i, j) {
				return Array.prototype.slice.call(a, i || 0, j || a.length);
			};
		}(),

		isIterable : function(v) {
			// check for array or arguments
			if (Ext.isArray(v) || v.callee) {
				return true;
			}
			// check for node list type
			if (/NodeList|HTMLCollection/.test(toString.call(v))) {
				return true;
			}
			// NodeList has an item and length property
			// IXMLDOMNodeList has nextNode method, needs to be checked first.
			return ((typeof v.nextNode != 'undefined' || v.item) && Ext
					.isNumber(v.length));
		},

		/**
		 * Iterates an array calling the supplied function.
		 * 
		 * @param {Array/NodeList/Mixed}
		 *            array The array to be iterated. If this argument is not
		 *            really an array, the supplied function is called once.
		 * @param {Function}
		 *            fn The function to be called with each item. If the
		 *            supplied function returns false, iteration stops and this
		 *            method returns the current <code>index</code>. This
		 *            function is called with the following arguments: <div
		 *            class="mdetail-params">
		 *            <ul>
		 *            <li><code>item</code> : <i>Mixed</i> <div
		 *            class="sub-desc">The item at the current
		 *            <code>index</code> in the passed <code>array</code></div></li>
		 *            <li><code>index</code> : <i>Number</i> <div
		 *            class="sub-desc">The current index within the array</div></li>
		 *            <li><code>allItems</code> : <i>Array</i> <div
		 *            class="sub-desc">The <code>array</code> passed as the
		 *            first argument to <code>Ext.each</code>.</div></li>
		 *            </ul>
		 *            </div>
		 * @param {Object}
		 *            scope The scope (<code>this</code> reference) in which
		 *            the specified function is executed. Defaults to the
		 *            <code>item</code> at the current <code>index</code>
		 *            within the passed <code>array</code>.
		 * @return See description for the fn parameter.
		 */
		each : function(array, fn, scope) {
			if (Ext.isEmpty(array, true)) {
				return;
			}
			if (!Ext.isIterable(array) || Ext.isPrimitive(array)) {
				array = [array];
			}
			for (var i = 0, len = array.length; i < len; i++) {
				if (fn.call(scope || array[i], array[i], i, array) === false) {
					return i;
				};
			}
		},

		/**
		 * Iterates either the elements in an array, or each of the properties
		 * in an object. <b>Note</b>: If you are only iterating arrays, it is
		 * better to call {@link #each}.
		 * 
		 * @param {Object/Array}
		 *            object The object or array to be iterated
		 * @param {Function}
		 *            fn The function to be called for each iteration. The
		 *            iteration will stop if the supplied function returns
		 *            false, or all array elements / object properties have been
		 *            covered. The signature varies depending on the type of
		 *            object being interated: <div class="mdetail-params">
		 *            <ul>
		 *            <li>Arrays :
		 *            <tt>(Object item, Number index, Array allItems)</tt>
		 *            <div class="sub-desc"> When iterating an array, the
		 *            supplied function is called with each item.</div></li>
		 *            <li>Objects : <tt>(String key, Object value, Object)</tt>
		 *            <div class="sub-desc"> When iterating an object, the
		 *            supplied function is called with each key-value pair in
		 *            the object, and the iterated object</div></li>
		 *            </ul>
		 *            </div>
		 * @param {Object}
		 *            scope The scope (<code>this</code> reference) in which
		 *            the specified function is executed. Defaults to the
		 *            <code>object</code> being iterated.
		 */
		iterate : function(obj, fn, scope) {
			if (Ext.isEmpty(obj)) {
				return;
			}
			if (Ext.isIterable(obj)) {
				Ext.each(obj, fn, scope);
				return;
			} else if (typeof obj == 'object') {
				for (var prop in obj) {
					if (obj.hasOwnProperty(prop)) {
						if (fn.call(scope || obj, prop, obj[prop], obj) === false) {
							return;
						};
					}
				}
			}
		},

		/**
		 * Return the dom node for the passed String (id), dom node, or
		 * Ext.Element. Optional 'strict' flag is needed for IE since it can
		 * return 'name' and 'id' elements by using getElementById. Here are
		 * some examples:
		 * 
		 * <pre><code>
		 * 		// gets dom node based on id
		 * 		var elDom = Ext.getDom('elId');
		 * 		// gets dom node based on the dom node
		 * 		var elDom1 = Ext.getDom(elDom);
		 * 
		 * 		// If we don 't know if we are working with an
		 * 		// Ext.Element or a dom node use Ext.getDom
		 * 		function(el){
		 * 		var dom = Ext.getDom(el);
		 * 		// do something with the dom node
		 * 		}
		 * </code></pre>
		 * 
		 * <b>Note</b>: the dom node to be found actually needs to exist (be
		 * rendered, etc) when this method is called to be successful.
		 * 
		 * @param {Mixed}
		 *            el
		 * @return HTMLElement
		 */
		getDom : function(el, strict) {
			if (!el || !DOC) {
				return null;
			}
			if (el.dom) {
				return el.dom;
			} else {
				if (typeof el == 'string') {
					var e = DOC.getElementById(el);
					// IE returns elements with the 'name' and 'id' attribute.
					// we do a strict check to return the element with only the
					// id attribute
					if (e && isIE && strict) {
						if (el == e.getAttribute('id')) {
							return e;
						} else {
							return null;
						}
					}
					return e;
				} else {
					return el;
				}
			}
		},

		/**
		 * Returns the current document body as an {@link Ext.Element}.
		 * 
		 * @return Ext.Element The document body
		 */
		getBody : function() {
			return Ext.get(DOC.body || DOC.documentElement);
		},

		/**
		 * Returns the current document body as an {@link Ext.Element}.
		 * 
		 * @return Ext.Element The document body
		 */
		getHead : function() {
			var head;

			return function() {
				if (head == undefined) {
					head = Ext.get(DOC.getElementsByTagName("head")[0]);
				}

				return head;
			};
		}(),

		/**
		 * Removes a DOM node from the document.
		 */
		/**
		 * <p>
		 * Removes this element from the document, removes all DOM event
		 * listeners, and deletes the cache reference. All DOM event listeners
		 * are removed from this element. If
		 * {@link Ext#enableNestedListenerRemoval} is <code>true</code>, then
		 * DOM event listeners are also removed from all child nodes. The body
		 * node will be ignored if passed in.
		 * </p>
		 * 
		 * @param {HTMLElement}
		 *            node The node to remove
		 */
		removeNode : isIE && !isIE8 ? function() {
			var d;
			return function(n) {
				if (n && n.tagName != 'BODY') {
					(Ext.enableNestedListenerRemoval) ? Ext.EventManager
							.purgeElement(n, true) : Ext.EventManager
							.removeAll(n);
					d = d || DOC.createElement('div');
					d.appendChild(n);
					d.innerHTML = '';
					delete Ext.elCache[n.id];
				}
			};
		}() : function(n) {
			if (n && n.parentNode && n.tagName != 'BODY') {
				(Ext.enableNestedListenerRemoval) ? Ext.EventManager
						.purgeElement(n, true) : Ext.EventManager.removeAll(n);
				n.parentNode.removeChild(n);
				delete Ext.elCache[n.id];
			}
		},

		/**
		 * <p>
		 * Returns true if the passed value is empty.
		 * </p>
		 * <p>
		 * The value is deemed to be empty if it is<div class="mdetail-params">
		 * <ul>
		 * <li>null</li>
		 * <li>undefined</li>
		 * <li>an empty array</li>
		 * <li>a zero length string (Unless the <tt>allowBlank</tt> parameter
		 * is <tt>true</tt>)</li>
		 * </ul>
		 * </div>
		 * 
		 * @param {Mixed}
		 *            value The value to test
		 * @param {Boolean}
		 *            allowBlank (optional) true to allow empty strings
		 *            (defaults to false)
		 * @return {Boolean}
		 */
		isEmpty : function(v, allowBlank) {
			return v === null || v === undefined
					|| ((Ext.isArray(v) && !v.length))
					|| (!allowBlank ? v === '' : false);
		},

		/**
		 * Returns true if the passed value is a JavaScript array, otherwise
		 * false.
		 * 
		 * @param {Mixed}
		 *            value The value to test
		 * @return {Boolean}
		 */
		isArray : function(v) {
			return toString.apply(v) === '[object Array]';
		},

		/**
		 * Returns true if the passed object is a JavaScript date object,
		 * otherwise false.
		 * 
		 * @param {Object}
		 *            object The object to test
		 * @return {Boolean}
		 */
		isDate : function(v) {
			return toString.apply(v) === '[object Date]';
		},

		/**
		 * Returns true if the passed value is a JavaScript Object, otherwise
		 * false.
		 * 
		 * @param {Mixed}
		 *            value The value to test
		 * @return {Boolean}
		 */
		isObject : function(v) {
			return !!v
					&& Object.prototype.toString.call(v) === '[object Object]';
		},

		/**
		 * Returns true if the passed value is a JavaScript 'primitive', a
		 * string, number or boolean.
		 * 
		 * @param {Mixed}
		 *            value The value to test
		 * @return {Boolean}
		 */
		isPrimitive : function(v) {
			return Ext.isString(v) || Ext.isNumber(v) || Ext.isBoolean(v);
		},

		/**
		 * Returns true if the passed value is a JavaScript Function, otherwise
		 * false.
		 * 
		 * @param {Mixed}
		 *            value The value to test
		 * @return {Boolean}
		 */
		isFunction : function(v) {
			return toString.apply(v) === '[object Function]';
		},

		/**
		 * Returns true if the passed value is a number. Returns false for
		 * non-finite numbers.
		 * 
		 * @param {Mixed}
		 *            value The value to test
		 * @return {Boolean}
		 */
		isNumber : function(v) {
			return typeof v === 'number' && isFinite(v);
		},

		/**
		 * Returns true if the passed value is a string.
		 * 
		 * @param {Mixed}
		 *            value The value to test
		 * @return {Boolean}
		 */
		isString : function(v) {
			return typeof v === 'string';
		},

		/**
		 * Returns true if the passed value is a boolean.
		 * 
		 * @param {Mixed}
		 *            value The value to test
		 * @return {Boolean}
		 */
		isBoolean : function(v) {
			return typeof v === 'boolean';
		},

		/**
		 * Returns true if the passed value is an HTMLElement
		 * 
		 * @param {Mixed}
		 *            value The value to test
		 * @return {Boolean}
		 */
		isElement : function(v) {
			return v ? !!v.tagName : false;
		},

		/**
		 * Returns true if the passed value is not undefined.
		 * 
		 * @param {Mixed}
		 *            value The value to test
		 * @return {Boolean}
		 */
		isDefined : function(v) {
			return typeof v !== 'undefined';
		},

		/**
		 * True if the detected browser is Opera.
		 * 
		 * @type Boolean
		 */
		isOpera : isOpera,
		/**
		 * True if the detected browser uses WebKit.
		 * 
		 * @type Boolean
		 */
		isWebKit : isWebKit,
		/**
		 * True if the detected browser is Chrome.
		 * 
		 * @type Boolean
		 */
		isChrome : isChrome,
		/**
		 * True if the detected browser is Safari.
		 * 
		 * @type Boolean
		 */
		isSafari : isSafari,
		/**
		 * True if the detected browser is Safari 3.x.
		 * 
		 * @type Boolean
		 */
		isSafari3 : isSafari3,
		/**
		 * True if the detected browser is Safari 4.x.
		 * 
		 * @type Boolean
		 */
		isSafari4 : isSafari4,
		/**
		 * True if the detected browser is Safari 2.x.
		 * 
		 * @type Boolean
		 */
		isSafari2 : isSafari2,
		/**
		 * True if the detected browser is Internet Explorer.
		 * 
		 * @type Boolean
		 */
		isIE : isIE,
		/**
		 * True if the detected browser is Internet Explorer 6.x.
		 * 
		 * @type Boolean
		 */
		isIE6 : isIE6,
		/**
		 * True if the detected browser is Internet Explorer 7.x.
		 * 
		 * @type Boolean
		 */
		isIE7 : isIE7,
		/**
		 * True if the detected browser is Internet Explorer 8.x.
		 * 
		 * @type Boolean
		 */
		isIE8 : isIE8,
		/**
		 * True if the detected browser uses the Gecko layout engine (e.g.
		 * Mozilla, Firefox).
		 * 
		 * @type Boolean
		 */
		isGecko : isGecko,
		/**
		 * True if the detected browser uses a pre-Gecko 1.9 layout engine (e.g.
		 * Firefox 2.x).
		 * 
		 * @type Boolean
		 */
		isGecko2 : isGecko2,
		/**
		 * True if the detected browser uses a Gecko 1.9+ layout engine (e.g.
		 * Firefox 3.x).
		 * 
		 * @type Boolean
		 */
		isGecko3 : isGecko3,
		/**
		 * True if the detected browser is Internet Explorer running in
		 * non-strict mode.
		 * 
		 * @type Boolean
		 */
		isBorderBox : isBorderBox,
		/**
		 * True if the detected platform is Linux.
		 * 
		 * @type Boolean
		 */
		isLinux : isLinux,
		/**
		 * True if the detected platform is Windows.
		 * 
		 * @type Boolean
		 */
		isWindows : isWindows,
		/**
		 * True if the detected platform is Mac OS.
		 * 
		 * @type Boolean
		 */
		isMac : isMac,
		/**
		 * True if the detected platform is Adobe Air.
		 * 
		 * @type Boolean
		 */
		isAir : isAir
	});

	/**
	 * Creates namespaces to be used for scoping variables and classes so that
	 * they are not global. Specifying the last node of a namespace implicitly
	 * creates all other nodes. Usage:
	 * 
	 * <pre><code>
	 * 	Ext.namespace('Company', 'Company.data');
	 * 	Ext.namespace('Company.data'); // equivalent and preferable to above syntax
	 * 	Company.Widget = function() { ... }
	 * 	Company.data.CustomStore = function(config) { ... }
	 * 	
	 * </code></pre>
	 * 
	 * @param {String}
	 *            namespace1
	 * @param {String}
	 *            namespace2
	 * @param {String}
	 *            etc
	 * @return {Object} The namespace object. (If multiple arguments are passed,
	 *         this will be the last namespace created)
	 * @method ns
	 */
	Ext.ns = Ext.namespace;
})();

Ext.ns('Ext.util', 'Ext.lib', 'Ext.data', 'Ext.supports');

Ext.elCache = {};

/**
 * @class Function These functions are available on every Function object (any
 *        JavaScript function).
 */
Ext.apply(Function.prototype, {
			/**
			 * Creates an interceptor function. The passed function is called
			 * before the original one. If it returns false, the original one is
			 * not called. The resulting function returns the results of the
			 * original function. The passed function is called with the
			 * parameters of the original function. Example usage:
			 * 
			 * <pre><code>
			 * var sayHi = function(name) {
			 * 	alert('Hi, ' + name);
			 * }
			 * 
			 * sayHi('Fred'); // alerts &quot;Hi, Fred&quot;
			 * 
			 * // create a new function that validates input without
			 * // directly modifying the original function:
			 * var sayHiToFriend = sayHi.createInterceptor(function(name) {
			 * 			return name == 'Brian';
			 * 		});
			 * 
			 * sayHiToFriend('Fred'); // no alert
			 * sayHiToFriend('Brian'); // alerts &quot;Hi, Brian&quot;
			 * </code></pre>
			 * 
			 * @param {Function}
			 *            fcn The function to call before the original
			 * @param {Object}
			 *            scope (optional) The scope (<code><b>this</b></code>
			 *            reference) in which the passed function is executed.
			 *            <b>If omitted, defaults to the scope in which the
			 *            original function is called or the browser window.</b>
			 * @return {Function} The new function
			 */
			createInterceptor : function(fcn, scope) {
				var method = this;
				return !Ext.isFunction(fcn) ? this : function() {
					var me = this, args = arguments;
					fcn.target = me;
					fcn.method = method;
					return (fcn.apply(scope || me || window, args) !== false)
							? method.apply(me || window, args)
							: null;
				};
			},

			/**
			 * Creates a callback that passes arguments[0], arguments[1],
			 * arguments[2], ... Call directly on any function. Example:
			 * <code>myFunction.createCallback(arg1, arg2)</code> Will create
			 * a function that is bound to those 2 args. <b>If a specific scope
			 * is required in the callback, use {@link #createDelegate} instead.</b>
			 * The function returned by createCallback always executes in the
			 * window scope.
			 * <p>
			 * This method is required when you want to pass arguments to a
			 * callback function. If no arguments are needed, you can simply
			 * pass a reference to the function as a callback (e.g., callback:
			 * myFn). However, if you tried to pass a function with arguments
			 * (e.g., callback: myFn(arg1, arg2)) the function would simply
			 * execute immediately when the code is parsed. Example usage:
			 * 
			 * <pre><code>
			 * var sayHi = function(name) {
			 * 	alert('Hi, ' + name);
			 * }
			 * 
			 * // clicking the button alerts &quot;Hi, Fred&quot;
			 * new Ext.Button({
			 * 			text : 'Say Hi',
			 * 			renderTo : Ext.getBody(),
			 * 			handler : sayHi.createCallback('Fred')
			 * 		});
			 * </code></pre>
			 * 
			 * @return {Function} The new function
			 */
			createCallback : function(/* args... */) {
				// make args available, in function below
				var args = arguments, method = this;
				return function() {
					return method.apply(window, args);
				};
			},

			/**
			 * Creates a delegate (callback) that sets the scope to obj. Call
			 * directly on any function. Example:
			 * <code>this.myFunction.createDelegate(this, [arg1, arg2])</code>
			 * Will create a function that is automatically scoped to obj so
			 * that the <tt>this</tt> variable inside the callback points to
			 * obj. Example usage:
			 * 
			 * <pre><code>
			 * var sayHi = function(name) {
			 * 	// Note this use of &quot;this.text&quot; here.  This function expects to
			 * 	// execute within a scope that contains a text property.  In this
			 * 	// example, the &quot;this&quot; variable is pointing to the btn object that
			 * 	// was passed in createDelegate below.
			 * 	alert('Hi, ' + name + '. You clicked the &quot;' + this.text + '&quot; button.');
			 * }
			 * 
			 * var btn = new Ext.Button({
			 * 			text : 'Say Hi',
			 * 			renderTo : Ext.getBody()
			 * 		});
			 * 
			 * // This callback will execute in the scope of the
			 * // button instance. Clicking the button alerts
			 * // &quot;Hi, Fred. You clicked the &quot;Say Hi&quot; button.&quot;
			 * btn.on('click', sayHi.createDelegate(btn, ['Fred']));
			 * </code></pre>
			 * 
			 * @param {Object}
			 *            scope (optional) The scope (<code><b>this</b></code>
			 *            reference) in which the function is executed. <b>If
			 *            omitted, defaults to the browser window.</b>
			 * @param {Array}
			 *            args (optional) Overrides arguments for the call.
			 *            (Defaults to the arguments passed by the caller)
			 * @param {Boolean/Number}
			 *            appendArgs (optional) if True args are appended to
			 *            call args instead of overriding, if a number the args
			 *            are inserted at the specified position
			 * @return {Function} The new function
			 */
			createDelegate : function(obj, args, appendArgs) {
				var method = this;
				return function() {
					var callArgs = args || arguments;
					if (appendArgs === true) {
						callArgs = Array.prototype.slice.call(arguments, 0);
						callArgs = callArgs.concat(args);
					} else if (Ext.isNumber(appendArgs)) {
						callArgs = Array.prototype.slice.call(arguments, 0); // copy
																				// arguments
																				// first
						var applyArgs = [appendArgs, 0].concat(args); // create
																		// method
																		// call
																		// params
						Array.prototype.splice.apply(callArgs, applyArgs); // splice
																			// them
																			// in
					}
					return method.apply(obj || window, callArgs);
				};
			},

			/**
			 * Calls this function after the number of millseconds specified,
			 * optionally in a specific scope. Example usage:
			 * 
			 * <pre><code>
			 * var sayHi = function(name) {
			 * 	alert('Hi, ' + name);
			 * }
			 * 
			 * // executes immediately:
			 * sayHi('Fred');
			 * 
			 * // executes after 2 seconds:
			 * sayHi.defer(2000, this, ['Fred']);
			 * 
			 * // this syntax is sometimes useful for deferring
			 * // execution of an anonymous function:
			 * (function() {
			 * 	alert('Anonymous');
			 * }).defer(100);
			 * </code></pre>
			 * 
			 * @param {Number}
			 *            millis The number of milliseconds for the setTimeout
			 *            call (if less than or equal to 0 the function is
			 *            executed immediately)
			 * @param {Object}
			 *            scope (optional) The scope (<code><b>this</b></code>
			 *            reference) in which the function is executed. <b>If
			 *            omitted, defaults to the browser window.</b>
			 * @param {Array}
			 *            args (optional) Overrides arguments for the call.
			 *            (Defaults to the arguments passed by the caller)
			 * @param {Boolean/Number}
			 *            appendArgs (optional) if True args are appended to
			 *            call args instead of overriding, if a number the args
			 *            are inserted at the specified position
			 * @return {Number} The timeout id that can be used with
			 *         clearTimeout
			 */
			defer : function(millis, obj, args, appendArgs) {
				var fn = this.createDelegate(obj, args, appendArgs);
				if (millis > 0) {
					return setTimeout(fn, millis);
				}
				fn();
				return 0;
			}
		});

/**
 * @class String These functions are available on every String object.
 */
Ext.applyIf(String, {
			/**
			 * Allows you to define a tokenized string and pass an arbitrary
			 * number of arguments to replace the tokens. Each token must be
			 * unique, and must increment in the format {0}, {1}, etc. Example
			 * usage:
			 * 
			 * <pre><code>
			 * var cls = 'my-class', text = 'Some text';
			 * var s = String.format('&lt;div class=&quot;{0}&quot;&gt;{1}&lt;/div&gt;', cls, text);
			 * // s now contains the string: '&lt;div class=&quot;my-class&quot;&gt;Some text&lt;/div&gt;'
			 * </code></pre>
			 * 
			 * @param {String}
			 *            string The tokenized string to be formatted
			 * @param {String}
			 *            value1 The value to replace token {0}
			 * @param {String}
			 *            value2 Etc...
			 * @return {String} The formatted string
			 * @static
			 */
			format : function(format) {
				var args = Ext.toArray(arguments, 1);
				return format.replace(/\{(\d+)\}/g, function(m, i) {
							return args[i];
						});
			}
		});

/**
 * @class Array
 */
Ext.applyIf(Array.prototype, {
			/**
			 * Checks whether or not the specified object exists in the array.
			 * 
			 * @param {Object}
			 *            o The object to check for
			 * @param {Number}
			 *            from (Optional) The index at which to begin the search
			 * @return {Number} The index of o in the array (or -1 if it is not
			 *         found)
			 */
			indexOf : function(o, from) {
				var len = this.length;
				from = from || 0;
				from += (from < 0) ? len : 0;
				for (; from < len; ++from) {
					if (this[from] === o) {
						return from;
					}
				}
				return -1;
			},

			/**
			 * Removes the specified object from the array. If the object is not
			 * found nothing happens.
			 * 
			 * @param {Object}
			 *            o The object to remove
			 * @return {Array} this array
			 */
			remove : function(o) {
				var index = this.indexOf(o);
				if (index != -1) {
					this.splice(index, 1);
				}
				return this;
			}
		});
/**
 * @class Ext.util.TaskRunner Provides the ability to execute one or more
 *        arbitrary tasks in a multithreaded manner. Generally, you can use the
 *        singleton {@link Ext.TaskMgr} instead, but if needed, you can create
 *        separate instances of TaskRunner. Any number of separate tasks can be
 *        started at any time and will run independently of each other. Example
 *        usage:
 * 
 * <pre><code>
 * // Start a simple clock task that updates a div once per second
 * var updateClock = function() {
 * 	Ext.fly('clock').update(new Date().format('g:i:s A'));
 * }
 * var task = {
 * 	run : updateClock,
 * 	interval : 1000
 * 	//1 second
 * }
 * var runner = new Ext.util.TaskRunner();
 * runner.start(task);
 * 
 * // equivalent using TaskMgr
 * Ext.TaskMgr.start({
 * 			run : updateClock,
 * 			interval : 1000
 * 		});
 * </code></pre>
 * 
 * <p>
 * See the {@link #start} method for details about how to configure a task
 * object.
 * </p>
 * Also see {@link Ext.util.DelayedTask}.
 * 
 * @constructor
 * @param {Number}
 *            interval (optional) The minimum precision in milliseconds
 *            supported by this TaskRunner instance (defaults to 10)
 */
Ext.util.TaskRunner = function(interval) {
	interval = interval || 10;
	var tasks = [], removeQueue = [], id = 0, running = false,

	// private
	stopThread = function() {
		running = false;
		clearInterval(id);
		id = 0;
	},

	// private
	startThread = function() {
		if (!running) {
			running = true;
			id = setInterval(runTasks, interval);
		}
	},

	// private
	removeTask = function(t) {
		removeQueue.push(t);
		if (t.onStop) {
			t.onStop.apply(t.scope || t);
		}
	},

	// private
	runTasks = function() {
		var rqLen = removeQueue.length, now = new Date().getTime();

		if (rqLen > 0) {
			for (var i = 0; i < rqLen; i++) {
				tasks.remove(removeQueue[i]);
			}
			removeQueue = [];
			if (tasks.length < 1) {
				stopThread();
				return;
			}
		}
		for (var i = 0, t, itime, rt, len = tasks.length; i < len; ++i) {
			t = tasks[i];
			itime = now - t.taskRunTime;
			if (t.interval <= itime) {
				rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
				t.taskRunTime = now;
				if (rt === false || t.taskRunCount === t.repeat) {
					removeTask(t);
					return;
				}
			}
			if (t.duration && t.duration <= (now - t.taskStartTime)) {
				removeTask(t);
			}
		}
	};

	/**
	 * Starts a new task.
	 * 
	 * @method start
	 * @param {Object}
	 *            task
	 *            <p>
	 *            A config object that supports the following properties:
	 *            <ul>
	 *            <li><code>run</code> : Function<div class="sub-desc">
	 *            <p>
	 *            The function to execute each time the task is invoked. The
	 *            function will be called at each interval and passed the
	 *            <code>args</code> argument if specified, and the current
	 *            invocation count if not.
	 *            </p>
	 *            <p>
	 *            If a particular scope (<code>this</code> reference) is
	 *            required, be sure to specify it using the <code>scope</code>
	 *            argument.
	 *            </p>
	 *            <p>
	 *            Return <code>false</code> from this function to terminate
	 *            the task.
	 *            </p>
	 *            </div></li>
	 *            <li><code>interval</code> : Number<div
	 *            class="sub-desc">The frequency in milliseconds with which the
	 *            task should be invoked.</div></li>
	 *            <li><code>args</code> : Array<div
	 *            class="sub-desc">(optional) An array of arguments to be passed
	 *            to the function specified by <code>run</code>. If not
	 *            specified, the current invocation count is passed.</div></li>
	 *            <li><code>scope</code> : Object<div
	 *            class="sub-desc">(optional) The scope (<tt>this</tt>
	 *            reference) in which to execute the <code>run</code>
	 *            function. Defaults to the task config object.</div></li>
	 *            <li><code>duration</code> : Number<div
	 *            class="sub-desc">(optional) The length of time in milliseconds
	 *            to invoke the task before stopping automatically (defaults to
	 *            indefinite).</div></li>
	 *            <li><code>repeat</code> : Number<div
	 *            class="sub-desc">(optional) The number of times to invoke the
	 *            task before stopping automatically (defaults to indefinite).</div></li>
	 *            </ul>
	 *            </p>
	 *            <p>
	 *            Before each invocation, Ext injects the property
	 *            <code>taskRunCount</code> into the task object so that
	 *            calculations based on the repeat count can be performed.
	 *            </p>
	 * @return {Object} The task
	 */
	this.start = function(task) {
		tasks.push(task);
		task.taskStartTime = new Date().getTime();
		task.taskRunTime = 0;
		task.taskRunCount = 0;
		startThread();
		return task;
	};

	/**
	 * Stops an existing running task.
	 * 
	 * @method stop
	 * @param {Object}
	 *            task The task to stop
	 * @return {Object} The task
	 */
	this.stop = function(task) {
		removeTask(task);
		return task;
	};

	/**
	 * Stops all tasks that are currently running.
	 * 
	 * @method stopAll
	 */
	this.stopAll = function() {
		stopThread();
		for (var i = 0, len = tasks.length; i < len; i++) {
			if (tasks[i].onStop) {
				tasks[i].onStop();
			}
		}
		tasks = [];
		removeQueue = [];
	};
};

/**
 * @class Ext.TaskMgr
 * @extends Ext.util.TaskRunner A static {@link Ext.util.TaskRunner} instance
 *          that can be used to start and stop arbitrary tasks. See
 *          {@link Ext.util.TaskRunner} for supported methods and task config
 *          properties.
 * 
 * <pre><code>
 * // Start a simple clock task that updates a div once per second
 * var task = {
 * 	run : function() {
 * 		Ext.fly('clock').update(new Date().format('g:i:s A'));
 * 	},
 * 	interval : 1000
 * 	//1 second
 * }
 * Ext.TaskMgr.start(task);
 * </code></pre>
 * 
 * <p>
 *          See the {@link #start} method for details about how to configure a
 *          task object.
 *          </p>
 * @singleton
 */
Ext.TaskMgr = new Ext.util.TaskRunner();
(function() {
	var libFlyweight;

	function fly(el) {
		if (!libFlyweight) {
			libFlyweight = new Ext.Element.Flyweight();
		}
		libFlyweight.dom = el;
		return libFlyweight;
	}

	(function() {
		var doc = document, isCSS1 = doc.compatMode == "CSS1Compat", MAX = Math.max, ROUND = Math.round, PARSEINT = parseInt;

		Ext.lib.Dom = {
			isAncestor : function(p, c) {
				var ret = false;

				p = Ext.getDom(p);
				c = Ext.getDom(c);
				if (p && c) {
					if (p.contains) {
						return p.contains(c);
					} else if (p.compareDocumentPosition) {
						return !!(p.compareDocumentPosition(c) & 16);
					} else {
						while (c = c.parentNode) {
							ret = c == p || ret;
						}
					}
				}
				return ret;
			},

			getViewWidth : function(full) {
				return full ? this.getDocumentWidth() : this.getViewportWidth();
			},

			getViewHeight : function(full) {
				return full ? this.getDocumentHeight() : this
						.getViewportHeight();
			},

			getDocumentHeight : function() {
				return MAX(!isCSS1
								? doc.body.scrollHeight
								: doc.documentElement.scrollHeight, this
								.getViewportHeight());
			},

			getDocumentWidth : function() {
				return MAX(!isCSS1
								? doc.body.scrollWidth
								: doc.documentElement.scrollWidth, this
								.getViewportWidth());
			},

			getViewportHeight : function() {
				return Ext.isIE ? (Ext.isStrict
						? doc.documentElement.clientHeight
						: doc.body.clientHeight) : self.innerHeight;
			},

			getViewportWidth : function() {
				return !Ext.isStrict && !Ext.isOpera
						? doc.body.clientWidth
						: Ext.isIE
								? doc.documentElement.clientWidth
								: self.innerWidth;
			},

			getY : function(el) {
				return this.getXY(el)[1];
			},

			getX : function(el) {
				return this.getXY(el)[0];
			},

			getXY : function(el) {
				var p, pe, b, bt, bl, dbd, x = 0, y = 0, scroll, hasAbsolute, bd = (doc.body || doc.documentElement), ret = [
						0, 0];

				el = Ext.getDom(el);

				if (el != bd) {
					if (el.getBoundingClientRect) {
						b = el.getBoundingClientRect();
						scroll = fly(document).getScroll();
						ret = [ROUND(b.left + scroll.left),
								ROUND(b.top + scroll.top)];
					} else {
						p = el;
						hasAbsolute = fly(el).isStyle("position", "absolute");

						while (p) {
							pe = fly(p);
							x += p.offsetLeft;
							y += p.offsetTop;

							hasAbsolute = hasAbsolute
									|| pe.isStyle("position", "absolute");

							if (Ext.isGecko) {
								y += bt = PARSEINT(pe
												.getStyle("borderTopWidth"), 10)
										|| 0;
								x += bl = PARSEINT(pe
												.getStyle("borderLeftWidth"),
										10)
										|| 0;

								if (p != el
										&& !pe.isStyle('overflow', 'visible')) {
									x += bl;
									y += bt;
								}
							}
							p = p.offsetParent;
						}

						if (Ext.isSafari && hasAbsolute) {
							x -= bd.offsetLeft;
							y -= bd.offsetTop;
						}

						if (Ext.isGecko && !hasAbsolute) {
							dbd = fly(bd);
							x += PARSEINT(dbd.getStyle("borderLeftWidth"), 10)
									|| 0;
							y += PARSEINT(dbd.getStyle("borderTopWidth"), 10)
									|| 0;
						}

						p = el.parentNode;
						while (p && p != bd) {
							if (!Ext.isOpera
									|| (p.tagName != 'TR' && !fly(p).isStyle(
											"display", "inline"))) {
								x -= p.scrollLeft;
								y -= p.scrollTop;
							}
							p = p.parentNode;
						}
						ret = [x, y];
					}
				}
				return ret;
			},

			setXY : function(el, xy) {
				(el = Ext.fly(el, '_setXY')).position();

				var pts = el.translatePoints(xy), style = el.dom.style, pos;

				for (pos in pts) {
					if (!isNaN(pts[pos])) {
						style[pos] = pts[pos] + "px";
					}
				}
			},

			setX : function(el, x) {
				this.setXY(el, [x, false]);
			},

			setY : function(el, y) {
				this.setXY(el, [false, y]);
			}
		};
	})();
	Ext.lib.Event = function() {
		var loadComplete = false, unloadListeners = {}, retryCount = 0, onAvailStack = [], _interval, locked = false, win = window, doc = document,

		// constants
		POLL_RETRYS = 200, POLL_INTERVAL = 20, TYPE = 0, FN = 1, OBJ = 2, ADJ_SCOPE = 3, SCROLLLEFT = 'scrollLeft', SCROLLTOP = 'scrollTop', UNLOAD = 'unload', MOUSEOVER = 'mouseover', MOUSEOUT = 'mouseout',
		// private
		doAdd = function() {
			var ret;
			if (win.addEventListener) {
				ret = function(el, eventName, fn, capture) {
					if (eventName == 'mouseenter') {
						fn = fn.createInterceptor(checkRelatedTarget);
						el.addEventListener(MOUSEOVER, fn, (capture));
					} else if (eventName == 'mouseleave') {
						fn = fn.createInterceptor(checkRelatedTarget);
						el.addEventListener(MOUSEOUT, fn, (capture));
					} else {
						el.addEventListener(eventName, fn, (capture));
					}
					return fn;
				};
			} else if (win.attachEvent) {
				ret = function(el, eventName, fn, capture) {
					el.attachEvent("on" + eventName, fn);
					return fn;
				};
			} else {
				ret = function() {
				};
			}
			return ret;
		}(),
		// private
		doRemove = function() {
			var ret;
			if (win.removeEventListener) {
				ret = function(el, eventName, fn, capture) {
					if (eventName == 'mouseenter') {
						eventName = MOUSEOVER;
					} else if (eventName == 'mouseleave') {
						eventName = MOUSEOUT;
					}
					el.removeEventListener(eventName, fn, (capture));
				};
			} else if (win.detachEvent) {
				ret = function(el, eventName, fn) {
					el.detachEvent("on" + eventName, fn);
				};
			} else {
				ret = function() {
				};
			}
			return ret;
		}();

		function checkRelatedTarget(e) {
			return !elContains(e.currentTarget, pub.getRelatedTarget(e));
		}

		function elContains(parent, child) {
			if (parent && parent.firstChild) {
				while (child) {
					if (child === parent) {
						return true;
					}
					child = child.parentNode;
					if (child && (child.nodeType != 1)) {
						child = null;
					}
				}
			}
			return false;
		}

		// private
		function _tryPreloadAttach() {
			var ret = false, notAvail = [], element, i, v, override, tryAgain = !loadComplete
					|| (retryCount > 0);

			if (!locked) {
				locked = true;

				for (i = 0; i < onAvailStack.length; ++i) {
					v = onAvailStack[i];
					if (v && (element = doc.getElementById(v.id))) {
						if (!v.checkReady || loadComplete
								|| element.nextSibling || (doc && doc.body)) {
							override = v.override;
							element = override ? (override === true
									? v.obj
									: override) : element;
							v.fn.call(element, v.obj);
							onAvailStack.remove(v);
							--i;
						} else {
							notAvail.push(v);
						}
					}
				}

				retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;

				if (tryAgain) {
					startInterval();
				} else {
					clearInterval(_interval);
					_interval = null;
				}
				ret = !(locked = false);
			}
			return ret;
		}

		// private
		function startInterval() {
			if (!_interval) {
				var callback = function() {
					_tryPreloadAttach();
				};
				_interval = setInterval(callback, POLL_INTERVAL);
			}
		}

		// private
		function getScroll() {
			var dd = doc.documentElement, db = doc.body;
			if (dd && (dd[SCROLLTOP] || dd[SCROLLLEFT])) {
				return [dd[SCROLLLEFT], dd[SCROLLTOP]];
			} else if (db) {
				return [db[SCROLLLEFT], db[SCROLLTOP]];
			} else {
				return [0, 0];
			}
		}

		// private
		function getPageCoord(ev, xy) {
			ev = ev.browserEvent || ev;
			var coord = ev['page' + xy];
			if (!coord && coord !== 0) {
				coord = ev['client' + xy] || 0;

				if (Ext.isIE) {
					coord += getScroll()[xy == "X" ? 0 : 1];
				}
			}

			return coord;
		}

		var pub = {
			extAdapter : true,
			onAvailable : function(p_id, p_fn, p_obj, p_override) {
				onAvailStack.push({
							id : p_id,
							fn : p_fn,
							obj : p_obj,
							override : p_override,
							checkReady : false
						});

				retryCount = POLL_RETRYS;
				startInterval();
			},

			// This function should ALWAYS be called from Ext.EventManager
			addListener : function(el, eventName, fn) {
				el = Ext.getDom(el);
				if (el && fn) {
					if (eventName == UNLOAD) {
						if (unloadListeners[el.id] === undefined) {
							unloadListeners[el.id] = [];
						}
						unloadListeners[el.id].push([eventName, fn]);
						return fn;
					}
					return doAdd(el, eventName, fn, false);
				}
				return false;
			},

			// This function should ALWAYS be called from Ext.EventManager
			removeListener : function(el, eventName, fn) {
				el = Ext.getDom(el);
				var i, len, li, lis;
				if (el && fn) {
					if (eventName == UNLOAD) {
						if ((lis = unloadListeners[el.id]) !== undefined) {
							for (i = 0, len = lis.length; i < len; i++) {
								if ((li = lis[i]) && li[TYPE] == eventName
										&& li[FN] == fn) {
									unloadListeners[el.id].splice(i, 1);
								}
							}
						}
						return;
					}
					doRemove(el, eventName, fn, false);
				}
			},

			getTarget : function(ev) {
				ev = ev.browserEvent || ev;
				return this.resolveTextNode(ev.target || ev.srcElement);
			},

			resolveTextNode : Ext.isGecko ? function(node) {
				if (!node) {
					return;
				}
				// work around firefox bug,
				// https://bugzilla.mozilla.org/show_bug.cgi?id=101197
				var s = HTMLElement.prototype.toString.call(node);
				if (s == '[xpconnect wrapped native prototype]'
						|| s == '[object XULElement]') {
					return;
				}
				return node.nodeType == 3 ? node.parentNode : node;
			} : function(node) {
				return node && node.nodeType == 3 ? node.parentNode : node;
			},

			getRelatedTarget : function(ev) {
				ev = ev.browserEvent || ev;
				return this.resolveTextNode(ev.relatedTarget
						|| (/(mouseout|mouseleave)/.test(ev.type)
								? ev.toElement
								: /(mouseover|mouseenter)/.test(ev.type)
										? ev.fromElement
										: null));
			},

			getPageX : function(ev) {
				return getPageCoord(ev, "X");
			},

			getPageY : function(ev) {
				return getPageCoord(ev, "Y");
			},

			getXY : function(ev) {
				return [this.getPageX(ev), this.getPageY(ev)];
			},

			stopEvent : function(ev) {
				this.stopPropagation(ev);
				this.preventDefault(ev);
			},

			stopPropagation : function(ev) {
				ev = ev.browserEvent || ev;
				if (ev.stopPropagation) {
					ev.stopPropagation();
				} else {
					ev.cancelBubble = true;
				}
			},

			preventDefault : function(ev) {
				ev = ev.browserEvent || ev;
				if (ev.preventDefault) {
					ev.preventDefault();
				} else {
					ev.returnValue = false;
				}
			},

			getEvent : function(e) {
				e = e || win.event;
				if (!e) {
					var c = this.getEvent.caller;
					while (c) {
						e = c.arguments[0];
						if (e && Event == e.constructor) {
							break;
						}
						c = c.caller;
					}
				}
				return e;
			},

			getCharCode : function(ev) {
				ev = ev.browserEvent || ev;
				return ev.charCode || ev.keyCode || 0;
			},

			// clearCache: function() {},
			// deprecated, call from EventManager
			getListeners : function(el, eventName) {
				Ext.EventManager.getListeners(el, eventName);
			},

			// deprecated, call from EventManager
			purgeElement : function(el, recurse, eventName) {
				Ext.EventManager.purgeElement(el, recurse, eventName);
			},

			_load : function(e) {
				loadComplete = true;

				if (Ext.isIE && e !== true) {
					// IE8 complains that _load is null or not an object
					// so lets remove self via arguments.callee
					doRemove(win, "load", arguments.callee);
				}
			},

			_unload : function(e) {
				var EU = Ext.lib.Event, i, v, ul, id, len, scope;

				for (id in unloadListeners) {
					ul = unloadListeners[id];
					for (i = 0, len = ul.length; i < len; i++) {
						v = ul[i];
						if (v) {
							try {
								scope = v[ADJ_SCOPE] ? (v[ADJ_SCOPE] === true
										? v[OBJ]
										: v[ADJ_SCOPE]) : win;
								v[FN].call(scope, EU.getEvent(e), v[OBJ]);
							} catch (ex) {
							}
						}
					}
				};

				Ext.EventManager._unload();

				doRemove(win, UNLOAD, EU._unload);
			}
		};

		// Initialize stuff.
		pub.on = pub.addListener;
		pub.un = pub.removeListener;
		if (doc && doc.body) {
			pub._load(true);
		} else {
			doAdd(win, "load", pub._load);
		}
		doAdd(win, UNLOAD, pub._unload);
		_tryPreloadAttach();

		return pub;
	}();
	/*
	 * Portions of this file are based on pieces of Yahoo User Interface Library
	 * Copyright (c) 2007, Yahoo! Inc. All rights reserved. YUI licensed under
	 * the BSD License: http://developer.yahoo.net/yui/license.txt
	 */
	Ext.lib.Ajax = function() {
		var activeX = ['Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.3.0',
				'Msxml2.XMLHTTP'], CONTENTTYPE = 'Content-Type';

		// private
		function setHeader(o) {
			var conn = o.conn, prop, headers = {};

			function setTheHeaders(conn, headers) {
				for (prop in headers) {
					if (headers.hasOwnProperty(prop)) {
						conn.setRequestHeader(prop, headers[prop]);
					}
				}
			}

			Ext.apply(headers, pub.headers, pub.defaultHeaders);
			setTheHeaders(conn, headers);
			delete pub.headers;
		}

		// private
		function createExceptionObject(tId, callbackArg, isAbort, isTimeout) {
			return {
				tId : tId,
				status : isAbort ? -1 : 0,
				statusText : isAbort
						? 'transaction aborted'
						: 'communication failure',
				isAbort : isAbort,
				isTimeout : isTimeout,
				argument : callbackArg
			};
		}

		// private
		function initHeader(label, value) {
			(pub.headers = pub.headers || {})[label] = value;
		}

		// private
		function createResponseObject(o, callbackArg) {
			var headerObj = {}, headerStr, conn = o.conn, t, s,
			// see:
			// https://prototype.lighthouseapp.com/projects/8886/tickets/129-ie-mangles-http-response-status-code-204-to-1223
			isBrokenStatus = conn.status == 1223;

			try {
				headerStr = o.conn.getAllResponseHeaders();
				Ext.each(headerStr.replace(/\r\n/g, '\n').split('\n'),
						function(v) {
							t = v.indexOf(':');
							if (t >= 0) {
								s = v.substr(0, t).toLowerCase();
								if (v.charAt(t + 1) == ' ') {
									++t;
								}
								headerObj[s] = v.substr(t + 1);
							}
						});
			} catch (e) {
			}

			return {
				tId : o.tId,
				// Normalize the status and statusText when IE returns 1223, see
				// the above link.
				status : isBrokenStatus ? 204 : conn.status,
				statusText : isBrokenStatus ? 'No Content' : conn.statusText,
				getResponseHeader : function(header) {
					return headerObj[header.toLowerCase()];
				},
				getAllResponseHeaders : function() {
					return headerStr;
				},
				responseText : conn.responseText,
				responseXML : conn.responseXML,
				argument : callbackArg
			};
		}

		// private
		function releaseObject(o) {
			if (o.tId) {
				pub.conn[o.tId] = null;
			}
			o.conn = null;
			o = null;
		}

		// private
		function handleTransactionResponse(o, callback, isAbort, isTimeout) {
			if (!callback) {
				releaseObject(o);
				return;
			}

			var httpStatus, responseObject;

			try {
				if (o.conn.status !== undefined && o.conn.status != 0) {
					httpStatus = o.conn.status;
				} else {
					httpStatus = 13030;
				}
			} catch (e) {
				httpStatus = 13030;
			}

			if ((httpStatus >= 200 && httpStatus < 300)
					|| (Ext.isIE && httpStatus == 1223)) {
				responseObject = createResponseObject(o, callback.argument);
				if (callback.success) {
					if (!callback.scope) {
						callback.success(responseObject);
					} else {
						callback.success
								.apply(callback.scope, [responseObject]);
					}
				}
			} else {
				switch (httpStatus) {
					case 12002 :
					case 12029 :
					case 12030 :
					case 12031 :
					case 12152 :
					case 13030 :
						responseObject = createExceptionObject(o.tId,
								callback.argument, (isAbort ? isAbort : false),
								isTimeout);
						if (callback.failure) {
							if (!callback.scope) {
								callback.failure(responseObject);
							} else {
								callback.failure.apply(callback.scope,
										[responseObject]);
							}
						}
						break;
					default :
						responseObject = createResponseObject(o,
								callback.argument);
						if (callback.failure) {
							if (!callback.scope) {
								callback.failure(responseObject);
							} else {
								callback.failure.apply(callback.scope,
										[responseObject]);
							}
						}
				}
			}

			releaseObject(o);
			responseObject = null;
		}

		function checkResponse(o, callback, conn, tId, poll, cbTimeout) {
			if (conn && conn.readyState == 4) {
				clearInterval(poll[tId]);
				poll[tId] = null;

				if (cbTimeout) {
					clearTimeout(pub.timeout[tId]);
					pub.timeout[tId] = null;
				}
				handleTransactionResponse(o, callback);
			}
		}

		function checkTimeout(o, callback) {
			pub.abort(o, callback, true);
		}

		// private
		function handleReadyState(o, callback) {
			callback = callback || {};
			var conn = o.conn, tId = o.tId, poll = pub.poll, cbTimeout = callback.timeout
					|| null;

			if (cbTimeout) {
				pub.conn[tId] = conn;
				pub.timeout[tId] = setTimeout(checkTimeout.createCallback(o,
								callback), cbTimeout);
			}
			poll[tId] = setInterval(checkResponse.createCallback(o, callback,
							conn, tId, poll, cbTimeout), pub.pollInterval);
		}

		// private
		function asyncRequest(method, uri, callback, postData) {
			var o = getConnectionObject() || null;

			if (o) {
				o.conn.open(method, uri, true);

				if (pub.useDefaultXhrHeader) {
					initHeader('X-Requested-With', pub.defaultXhrHeader);
				}

				if (postData && pub.useDefaultHeader
						&& (!pub.headers || !pub.headers[CONTENTTYPE])) {
					initHeader(CONTENTTYPE, pub.defaultPostHeader);
				}

				if (pub.defaultHeaders || pub.headers) {
					setHeader(o);
				}

				handleReadyState(o, callback);
				o.conn.send(postData || null);
			}
			return o;
		}

		// private
		function getConnectionObject() {
			var o;

			try {
				if (o = createXhrObject(pub.transactionId)) {
					pub.transactionId++;
				}
			} catch (e) {
			} finally {
				return o;
			}
		}

		// private
		function createXhrObject(transactionId) {
			var http;

			try {
				http = new XMLHttpRequest();
			} catch (e) {
				for (var i = 0; i < activeX.length; ++i) {
					try {
						http = new ActiveXObject(activeX[i]);
						break;
					} catch (e) {
					}
				}
			} finally {
				return {
					conn : http,
					tId : transactionId
				};
			}
		}

		var pub = {
			request : function(method, uri, cb, data, options) {
				if (options) {
					var me = this, xmlData = options.xmlData, jsonData = options.jsonData, hs;

					Ext.applyIf(me, options);

					if (xmlData || jsonData) {
						hs = me.headers;
						if (!hs || !hs[CONTENTTYPE]) {
							initHeader(CONTENTTYPE, xmlData
											? 'text/xml'
											: 'application/json');
						}
						data = xmlData
								|| (!Ext.isPrimitive(jsonData) ? Ext
										.encode(jsonData) : jsonData);
					}
				}
				return asyncRequest(method || options.method || "POST", uri,
						cb, data);
			},

			serializeForm : function(form) {
				var fElements = form.elements
						|| (document.forms[form] || Ext.getDom(form)).elements, hasSubmit = false, encoder = encodeURIComponent, name, data = '', type, hasValue;

				Ext.each(fElements, function(element) {
					name = element.name;
					type = element.type;

					if (!element.disabled && name) {
						if (/select-(one|multiple)/i.test(type)) {
							Ext.each(element.options, function(opt) {
								if (opt.selected) {
									hasValue = opt.hasAttribute
											? opt.hasAttribute('value')
											: opt.getAttributeNode('value').specified;
									data += String.format("{0}={1}&",
											encoder(name), encoder(hasValue
													? opt.value
													: opt.text));
								}
							});
						} else if (!(/file|undefined|reset|button/i.test(type))) {
							if (!(/radio|checkbox/i.test(type) && !element.checked)
									&& !(type == 'submit' && hasSubmit)) {
								data += encoder(name) + '='
										+ encoder(element.value) + '&';
								hasSubmit = /submit/i.test(type);
							}
						}
					}
				});
				return data.substr(0, data.length - 1);
			},

			useDefaultHeader : true,
			defaultPostHeader : 'application/x-www-form-urlencoded; charset=UTF-8',
			useDefaultXhrHeader : true,
			defaultXhrHeader : 'XMLHttpRequest',
			poll : {},
			timeout : {},
			conn : {},
			pollInterval : 50,
			transactionId : 0,

			// This is never called - Is it worth exposing this?
			// setProgId : function(id) {
			// activeX.unshift(id);
			// },

			// This is never called - Is it worth exposing this?
			// setDefaultPostHeader : function(b) {
			// this.useDefaultHeader = b;
			// },

			// This is never called - Is it worth exposing this?
			// setDefaultXhrHeader : function(b) {
			// this.useDefaultXhrHeader = b;
			// },

			// This is never called - Is it worth exposing this?
			// setPollingInterval : function(i) {
			// if (typeof i == 'number' && isFinite(i)) {
			// this.pollInterval = i;
			// }
			// },

			// This is never called - Is it worth exposing this?
			// resetDefaultHeaders : function() {
			// this.defaultHeaders = null;
			// },

			abort : function(o, callback, isTimeout) {
				var me = this, tId = o.tId, isAbort = false;

				if (me.isCallInProgress(o)) {
					o.conn.abort();
					clearInterval(me.poll[tId]);
					me.poll[tId] = null;
					clearTimeout(pub.timeout[tId]);
					me.timeout[tId] = null;

					handleTransactionResponse(o, callback, (isAbort = true),
							isTimeout);
				}
				return isAbort;
			},

			isCallInProgress : function(o) {
				// if there is a connection and readyState is not 0 or 4
				return o.conn && !{
					0 : true,
					4 : true
				}[o.conn.readyState];
			}
		};
		return pub;
	}();
	(function() {
		var EXTLIB = Ext.lib, noNegatives = /width|height|opacity|padding/i, offsetAttribute = /^((width|height)|(top|left))$/, defaultUnit = /width|height|top$|bottom$|left$|right$/i, offsetUnit = /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i, isset = function(
				v) {
			return typeof v !== 'undefined';
		}, now = function() {
			return new Date();
		};

		EXTLIB.Anim = {
			motion : function(el, args, duration, easing, cb, scope) {
				return this.run(el, args, duration, easing, cb, scope,
						Ext.lib.Motion);
			},

			run : function(el, args, duration, easing, cb, scope, type) {
				type = type || Ext.lib.AnimBase;
				if (typeof easing == "string") {
					easing = Ext.lib.Easing[easing];
				}
				var anim = new type(el, args, duration, easing);
				anim.animateX(function() {
							if (Ext.isFunction(cb)) {
								cb.call(scope);
							}
						});
				return anim;
			}
		};

		EXTLIB.AnimBase = function(el, attributes, duration, method) {
			if (el) {
				this.init(el, attributes, duration, method);
			}
		};

		EXTLIB.AnimBase.prototype = {
			doMethod : function(attr, start, end) {
				var me = this;
				return me.method(me.curFrame, start, end - start,
						me.totalFrames);
			},

			setAttr : function(attr, val, unit) {
				if (noNegatives.test(attr) && val < 0) {
					val = 0;
				}
				Ext.fly(this.el, '_anim').setStyle(attr, val + unit);
			},

			getAttr : function(attr) {
				var el = Ext.fly(this.el), val = el.getStyle(attr), a = offsetAttribute
						.exec(attr)
						|| [];

				if (val !== 'auto' && !offsetUnit.test(val)) {
					return parseFloat(val);
				}

				return (!!(a[2]) || (el.getStyle('position') == 'absolute' && !!(a[3])))
						? el.dom['offset' + a[0].charAt(0).toUpperCase()
								+ a[0].substr(1)]
						: 0;
			},

			getDefaultUnit : function(attr) {
				return defaultUnit.test(attr) ? 'px' : '';
			},

			animateX : function(callback, scope) {
				var me = this, f = function() {
					me.onComplete.removeListener(f);
					if (Ext.isFunction(callback)) {
						callback.call(scope || me, me);
					}
				};
				me.onComplete.addListener(f, me);
				me.animate();
			},

			setRunAttr : function(attr) {
				var me = this, a = this.attributes[attr], to = a.to, by = a.by, from = a.from, unit = a.unit, ra = (this.runAttrs[attr] = {}), end;

				if (!isset(to) && !isset(by)) {
					return false;
				}

				var start = isset(from) ? from : me.getAttr(attr);
				if (isset(to)) {
					end = to;
				} else if (isset(by)) {
					if (Ext.isArray(start)) {
						end = [];
						for (var i = 0, len = start.length; i < len; i++) {
							end[i] = start[i] + by[i];
						}
					} else {
						end = start + by;
					}
				}

				Ext.apply(ra, {
							start : start,
							end : end,
							unit : isset(unit) ? unit : me.getDefaultUnit(attr)
						});
			},

			init : function(el, attributes, duration, method) {
				var me = this, actualFrames = 0, mgr = EXTLIB.AnimMgr;

				Ext.apply(me, {
					isAnimated : false,
					startTime : null,
					el : Ext.getDom(el),
					attributes : attributes || {},
					duration : duration || 1,
					method : method || EXTLIB.Easing.easeNone,
					useSec : true,
					curFrame : 0,
					totalFrames : mgr.fps,
					runAttrs : {},
					animate : function() {
						var me = this, d = me.duration;

						if (me.isAnimated) {
							return false;
						}

						me.curFrame = 0;
						me.totalFrames = me.useSec ? Math.ceil(mgr.fps * d) : d;
						mgr.registerElement(me);
					},

					stop : function(finish) {
						var me = this;

						if (finish) {
							me.curFrame = me.totalFrames;
							me._onTween.fire();
						}
						mgr.stop(me);
					}
				});

				var onStart = function() {
					var me = this, attr;

					me.onStart.fire();
					me.runAttrs = {};
					for (attr in this.attributes) {
						this.setRunAttr(attr);
					}

					me.isAnimated = true;
					me.startTime = now();
					actualFrames = 0;
				};

				var onTween = function() {
					var me = this;

					me.onTween.fire({
								duration : now() - me.startTime,
								curFrame : me.curFrame
							});

					var ra = me.runAttrs;
					for (var attr in ra) {
						this.setAttr(attr, me.doMethod(attr, ra[attr].start,
										ra[attr].end), ra[attr].unit);
					}

					++actualFrames;
				};

				var onComplete = function() {
					var me = this, actual = (now() - me.startTime) / 1000, data = {
						duration : actual,
						frames : actualFrames,
						fps : actualFrames / actual
					};

					me.isAnimated = false;
					actualFrames = 0;
					me.onComplete.fire(data);
				};

				me.onStart = new Ext.util.Event(me);
				me.onTween = new Ext.util.Event(me);
				me.onComplete = new Ext.util.Event(me);
				(me._onStart = new Ext.util.Event(me)).addListener(onStart);
				(me._onTween = new Ext.util.Event(me)).addListener(onTween);
				(me._onComplete = new Ext.util.Event(me))
						.addListener(onComplete);
			}
		};

		Ext.lib.AnimMgr = new function() {
			var me = this, thread = null, queue = [], tweenCount = 0;

			Ext.apply(me, {
						fps : 1000,
						delay : 1,
						registerElement : function(tween) {
							queue.push(tween);
							++tweenCount;
							tween._onStart.fire();
							me.start();
						},

						unRegister : function(tween, index) {
							tween._onComplete.fire();
							index = index || getIndex(tween);
							if (index != -1) {
								queue.splice(index, 1);
							}

							if (--tweenCount <= 0) {
								me.stop();
							}
						},

						start : function() {
							if (thread === null) {
								thread = setInterval(me.run, me.delay);
							}
						},

						stop : function(tween) {
							if (!tween) {
								clearInterval(thread);
								for (var i = 0, len = queue.length; i < len; ++i) {
									if (queue[0].isAnimated) {
										me.unRegister(queue[0], 0);
									}
								}

								queue = [];
								thread = null;
								tweenCount = 0;
							} else {
								me.unRegister(tween);
							}
						},

						run : function() {
							var tf, i, len, tween;
							for (i = 0, len = queue.length; i < len; i++) {
								tween = queue[i];
								if (tween && tween.isAnimated) {
									tf = tween.totalFrames;
									if (tween.curFrame < tf || tf === null) {
										++tween.curFrame;
										if (tween.useSec) {
											correctFrame(tween);
										}
										tween._onTween.fire();
									} else {
										me.stop(tween);
									}
								}
							}
						}
					});

			var getIndex = function(anim) {
				var i, len;
				for (i = 0, len = queue.length; i < len; i++) {
					if (queue[i] === anim) {
						return i;
					}
				}
				return -1;
			};

			var correctFrame = function(tween) {
				var frames = tween.totalFrames, frame = tween.curFrame, duration = tween.duration, expected = (frame
						* duration * 1000 / frames), elapsed = (now() - tween.startTime), tweak = 0;

				if (elapsed < duration * 1000) {
					tweak = Math.round((elapsed / expected - 1) * frame);
				} else {
					tweak = frames - (frame + 1);
				}
				if (tweak > 0 && isFinite(tweak)) {
					if (tween.curFrame + tweak >= frames) {
						tweak = frames - (frame + 1);
					}
					tween.curFrame += tweak;
				}
			};
		};

		EXTLIB.Bezier = new function() {

			this.getPosition = function(points, t) {
				var n = points.length, tmp = [], c = 1 - t, i, j;

				for (i = 0; i < n; ++i) {
					tmp[i] = [points[i][0], points[i][1]];
				}

				for (j = 1; j < n; ++j) {
					for (i = 0; i < n - j; ++i) {
						tmp[i][0] = c * tmp[i][0] + t
								* tmp[parseInt(i + 1, 10)][0];
						tmp[i][1] = c * tmp[i][1] + t
								* tmp[parseInt(i + 1, 10)][1];
					}
				}

				return [tmp[0][0], tmp[0][1]];

			};
		};

		EXTLIB.Easing = {
			easeNone : function(t, b, c, d) {
				return c * t / d + b;
			},

			easeIn : function(t, b, c, d) {
				return c * (t /= d) * t + b;
			},

			easeOut : function(t, b, c, d) {
				return -c * (t /= d) * (t - 2) + b;
			}
		};

		(function() {
			EXTLIB.Motion = function(el, attributes, duration, method) {
				if (el) {
					EXTLIB.Motion.superclass.constructor.call(this, el,
							attributes, duration, method);
				}
			};

			Ext.extend(EXTLIB.Motion, Ext.lib.AnimBase);

			var superclass = EXTLIB.Motion.superclass, pointsRe = /^points$/i;

			Ext.apply(EXTLIB.Motion.prototype, {
				setAttr : function(attr, val, unit) {
					var me = this, setAttr = superclass.setAttr;

					if (pointsRe.test(attr)) {
						unit = unit || 'px';
						setAttr.call(me, 'left', val[0], unit);
						setAttr.call(me, 'top', val[1], unit);
					} else {
						setAttr.call(me, attr, val, unit);
					}
				},

				getAttr : function(attr) {
					var me = this, getAttr = superclass.getAttr;

					return pointsRe.test(attr) ? [getAttr.call(me, 'left'),
							getAttr.call(me, 'top')] : getAttr.call(me, attr);
				},

				doMethod : function(attr, start, end) {
					var me = this;

					return pointsRe.test(attr) ? EXTLIB.Bezier.getPosition(
							me.runAttrs[attr], me.method(me.curFrame, 0, 100,
									me.totalFrames)
									/ 100) : superclass.doMethod.call(me, attr,
							start, end);
				},

				setRunAttr : function(attr) {
					if (pointsRe.test(attr)) {

						var me = this, el = this.el, points = this.attributes.points, control = points.control
								|| [], from = points.from, to = points.to, by = points.by, DOM = EXTLIB.Dom, start, i, end, len, ra;

						if (control.length > 0 && !Ext.isArray(control[0])) {
							control = [control];
						} else {
							/*
							 * var tmp = []; for (i = 0,len = control.length; i <
							 * len; ++i) { tmp[i] = control[i]; } control = tmp;
							 */
						}

						Ext.fly(el, '_anim').position();
						DOM.setXY(el, isset(from) ? from : DOM.getXY(el));
						start = me.getAttr('points');

						if (isset(to)) {
							end = translateValues.call(me, to, start);
							for (i = 0, len = control.length; i < len; ++i) {
								control[i] = translateValues.call(me,
										control[i], start);
							}
						} else if (isset(by)) {
							end = [start[0] + by[0], start[1] + by[1]];

							for (i = 0, len = control.length; i < len; ++i) {
								control[i] = [start[0] + control[i][0],
										start[1] + control[i][1]];
							}
						}

						ra = this.runAttrs[attr] = [start];
						if (control.length > 0) {
							ra = ra.concat(control);
						}

						ra[ra.length] = end;
					} else {
						superclass.setRunAttr.call(this, attr);
					}
				}
			});

			var translateValues = function(val, start) {
				var pageXY = EXTLIB.Dom.getXY(this.el);
				return [val[0] - pageXY[0] + start[0],
						val[1] - pageXY[1] + start[1]];
			};
		})();
	})();// Easing functions
	(function() {
		// shortcuts to aid compression
		var abs = Math.abs, pi = Math.PI, asin = Math.asin, pow = Math.pow, sin = Math.sin, EXTLIB = Ext.lib;

		Ext.apply(EXTLIB.Easing, {

					easeBoth : function(t, b, c, d) {
						return ((t /= d / 2) < 1) ? c / 2 * t * t + b : -c / 2
								* ((--t) * (t - 2) - 1) + b;
					},

					easeInStrong : function(t, b, c, d) {
						return c * (t /= d) * t * t * t + b;
					},

					easeOutStrong : function(t, b, c, d) {
						return -c * ((t = t / d - 1) * t * t * t - 1) + b;
					},

					easeBothStrong : function(t, b, c, d) {
						return ((t /= d / 2) < 1)
								? c / 2 * t * t * t * t + b
								: -c / 2 * ((t -= 2) * t * t * t - 2) + b;
					},

					elasticIn : function(t, b, c, d, a, p) {
						if (t == 0 || (t /= d) == 1) {
							return t == 0 ? b : b + c;
						}
						p = p || (d * .3);

						var s;
						if (a >= abs(c)) {
							s = p / (2 * pi) * asin(c / a);
						} else {
							a = c;
							s = p / 4;
						}

						return -(a * pow(2, 10 * (t -= 1)) * sin((t * d - s)
								* (2 * pi) / p))
								+ b;

					},

					elasticOut : function(t, b, c, d, a, p) {
						if (t == 0 || (t /= d) == 1) {
							return t == 0 ? b : b + c;
						}
						p = p || (d * .3);

						var s;
						if (a >= abs(c)) {
							s = p / (2 * pi) * asin(c / a);
						} else {
							a = c;
							s = p / 4;
						}

						return a * pow(2, -10 * t)
								* sin((t * d - s) * (2 * pi) / p) + c + b;
					},

					elasticBoth : function(t, b, c, d, a, p) {
						if (t == 0 || (t /= d / 2) == 2) {
							return t == 0 ? b : b + c;
						}

						p = p || (d * (.3 * 1.5));

						var s;
						if (a >= abs(c)) {
							s = p / (2 * pi) * asin(c / a);
						} else {
							a = c;
							s = p / 4;
						}

						return t < 1 ? -.5
								* (a * pow(2, 10 * (t -= 1)) * sin((t * d - s)
										* (2 * pi) / p)) + b : a
								* pow(2, -10 * (t -= 1))
								* sin((t * d - s) * (2 * pi) / p) * .5 + c + b;
					},

					backIn : function(t, b, c, d, s) {
						s = s || 1.70158;
						return c * (t /= d) * t * ((s + 1) * t - s) + b;
					},

					backOut : function(t, b, c, d, s) {
						if (!s) {
							s = 1.70158;
						}
						return c
								* ((t = t / d - 1) * t * ((s + 1) * t + s) + 1)
								+ b;
					},

					backBoth : function(t, b, c, d, s) {
						s = s || 1.70158;

						return ((t /= d / 2) < 1)
								? c
										/ 2
										* (t * t * (((s *= (1.525)) + 1) * t - s))
										+ b
								: c
										/ 2
										* ((t -= 2)
												* t
												* (((s *= (1.525)) + 1) * t + s) + 2)
										+ b;
					},

					bounceIn : function(t, b, c, d) {
						return c - EXTLIB.Easing.bounceOut(d - t, 0, c, d) + b;
					},

					bounceOut : function(t, b, c, d) {
						if ((t /= d) < (1 / 2.75)) {
							return c * (7.5625 * t * t) + b;
						} else if (t < (2 / 2.75)) {
							return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75)
									+ b;
						} else if (t < (2.5 / 2.75)) {
							return c
									* (7.5625 * (t -= (2.25 / 2.75)) * t + .9375)
									+ b;
						}
						return c
								* (7.5625 * (t -= (2.625 / 2.75)) * t + .984375)
								+ b;
					},

					bounceBoth : function(t, b, c, d) {
						return (t < d / 2) ? EXTLIB.Easing.bounceIn(t * 2, 0,
								c, d)
								* .5 + b : EXTLIB.Easing.bounceOut(t * 2 - d,
								0, c, d)
								* .5 + c * .5 + b;
					}
				});
	})();

	(function() {
		var EXTLIB = Ext.lib;
		// Color Animation
		EXTLIB.Anim.color = function(el, args, duration, easing, cb, scope) {
			return EXTLIB.Anim.run(el, args, duration, easing, cb, scope,
					EXTLIB.ColorAnim);
		};

		EXTLIB.ColorAnim = function(el, attributes, duration, method) {
			EXTLIB.ColorAnim.superclass.constructor.call(this, el, attributes,
					duration, method);
		};

		Ext.extend(EXTLIB.ColorAnim, EXTLIB.AnimBase);

		var superclass = EXTLIB.ColorAnim.superclass, colorRE = /color$/i, transparentRE = /^transparent|rgba\(0, 0, 0, 0\)$/, rgbRE = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i, hexRE = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i, hex3RE = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i, isset = function(
				v) {
			return typeof v !== 'undefined';
		};

		// private
		function parseColor(s) {
			var pi = parseInt, base, out = null, c;

			if (s.length == 3) {
				return s;
			}

			Ext.each([hexRE, rgbRE, hex3RE], function(re, idx) {
						base = (idx % 2 == 0) ? 16 : 10;
						c = re.exec(s);
						if (c && c.length == 4) {
							out = [pi(c[1], base), pi(c[2], base),
									pi(c[3], base)];
							return false;
						}
					});
			return out;
		}

		Ext.apply(EXTLIB.ColorAnim.prototype, {
			getAttr : function(attr) {
				var me = this, el = me.el, val;
				if (colorRE.test(attr)) {
					while (el
							&& transparentRE.test(val = Ext.fly(el)
									.getStyle(attr))) {
						el = el.parentNode;
						val = "fff";
					}
				} else {
					val = superclass.getAttr.call(me, attr);
				}
				return val;
			},

			doMethod : function(attr, start, end) {
				var me = this, val, floor = Math.floor, i, len, v;

				if (colorRE.test(attr)) {
					val = [];
					end = end || [];

					for (i = 0, len = start.length; i < len; i++) {
						v = start[i];
						val[i] = superclass.doMethod.call(me, attr, v, end[i]);
					}
					val = 'rgb(' + floor(val[0]) + ',' + floor(val[1]) + ','
							+ floor(val[2]) + ')';
				} else {
					val = superclass.doMethod.call(me, attr, start, end);
				}
				return val;
			},

			setRunAttr : function(attr) {
				var me = this, a = me.attributes[attr], to = a.to, by = a.by, ra;

				superclass.setRunAttr.call(me, attr);
				ra = me.runAttrs[attr];
				if (colorRE.test(attr)) {
					var start = parseColor(ra.start), end = parseColor(ra.end);

					if (!isset(to) && isset(by)) {
						end = parseColor(by);
						for (var i = 0, len = start.length; i < len; i++) {
							end[i] = start[i] + end[i];
						}
					}
					ra.start = start;
					ra.end = end;
				}
			}
		});
	})();

	(function() {
		// Scroll Animation
		var EXTLIB = Ext.lib;
		EXTLIB.Anim.scroll = function(el, args, duration, easing, cb, scope) {
			return EXTLIB.Anim.run(el, args, duration, easing, cb, scope,
					EXTLIB.Scroll);
		};

		EXTLIB.Scroll = function(el, attributes, duration, method) {
			if (el) {
				EXTLIB.Scroll.superclass.constructor.call(this, el, attributes,
						duration, method);
			}
		};

		Ext.extend(EXTLIB.Scroll, EXTLIB.ColorAnim);

		var superclass = EXTLIB.Scroll.superclass, SCROLL = 'scroll';

		Ext.apply(EXTLIB.Scroll.prototype, {

			doMethod : function(attr, start, end) {
				var val, me = this, curFrame = me.curFrame, totalFrames = me.totalFrames;

				if (attr == SCROLL) {
					val = [
							me.method(curFrame, start[0], end[0] - start[0],
									totalFrames),
							me.method(curFrame, start[1], end[1] - start[1],
									totalFrames)];
				} else {
					val = superclass.doMethod.call(me, attr, start, end);
				}
				return val;
			},

			getAttr : function(attr) {
				var me = this;

				if (attr == SCROLL) {
					return [me.el.scrollLeft, me.el.scrollTop];
				} else {
					return superclass.getAttr.call(me, attr);
				}
			},

			setAttr : function(attr, val, unit) {
				var me = this;

				if (attr == SCROLL) {
					me.el.scrollLeft = val[0];
					me.el.scrollTop = val[1];
				} else {
					superclass.setAttr.call(me, attr, val, unit);
				}
			}
		});
	})();
	if (Ext.isIE) {
		function fnCleanUp() {
			var p = Function.prototype;
			delete p.createSequence;
			delete p.defer;
			delete p.createDelegate;
			delete p.createCallback;
			delete p.createInterceptor;

			window.detachEvent("onunload", fnCleanUp);
		}
		window.attachEvent("onunload", fnCleanUp);
	}
})();